﻿using AnyCAD.Foundation;
using System;
namespace Rapid.Sketch.Plugin
{

    class AddFollowingPointEditor: Editor
    { 
        public AddFollowingPointEditor()
        {
            SetName("AddFollowingPoint");
        }

        public override EnumEditorCode Start(ViewContext ctx)
        {
            var tmp = ctx.GetTempContext();
            tmp.Start();
            tmp.SetPickFilter(EnumShapeFilter.Edge);
            return base.Start(ctx);
        }

        public override void Finish(ViewContext ctx)
        {
            ctx.GetTempContext().Close();
            base.Finish(ctx);
        }

        public override EnumEditorCode OnMouseMove(ViewContext ctx, InputEvent evt)
        {
            if (evt.GetButtons() == EnumMouseButton.Zero)
            {                
                var item = ctx.SnapPoint(evt.GetX(), evt.GetY());
                if(!item.IsNull())
                {
                    ctx.GetSelectionManager().GetHilight().Add(item, true);
                }
                else
                {
                    ctx.ClearSelection();
                }
                ctx.RequestUpdate(EnumUpdateFlags.Selection);
                return EnumEditorCode.Processed;
            }
        
            
            return base.OnMouseMove(ctx, evt);
        }

        EnumEditorCode AddMethod1(ViewContext ctx, InputEvent evt, PickedItem pickedItem)
        {
            var doc = ctx.GetDocument();
            var se = ShapeElement.Cast(doc.FindElement(pickedItem.GetId()));
            if (se == null)
                return EnumEditorCode.Processed;

            SnapShapeEngine sse = SnapShapeEngine.Get(ctx);
            var edge = sse.ParseSubShape(ctx, pickedItem);
            if (edge == null)
                return EnumEditorCode.Processed;

            var pc = new ParametricCurve(edge);
            if (!pc.IsValidGeometry())
                return EnumEditorCode.Processed;

            var u = pc.ComputeClosestPoint(pickedItem.GetPosition().ToPnt());
            if (u == double.NaN)
                return EnumEditorCode.Processed;

            var pt = pc.Value(u);

            pt.Transform(se.GetTransform().Inverted());

            UndoTransaction undo = new UndoTransaction(doc);
            undo.Start(GetName());

            var pe = PointElement.Create(doc);
            pe.SetValue(pt);
            pe.SetParentId(se.GetId());
            pe.SetTransformBehaviour(EnumTransformBehaviour.ByParent);

            undo.Commit();

            return EnumEditorCode.Processed;
        }

        EnumEditorCode AddMethod2(ViewContext ctx, InputEvent evt, PickedItem pickedItem)
        {
            var doc = ctx.GetDocument();
            var se = ShapeElement.Cast(doc.FindElement(pickedItem.GetId()));
            if(se == null) 
                return EnumEditorCode.Processed;

            var shape = se.GetFinalShape();

            var edge = shape.FindChild(EnumTopoShapeType.Topo_EDGE, pickedItem.GetTopoShapeId());
            if (edge == null)
                return EnumEditorCode.Processed;


            var pc = new ParametricCurve(edge);
            if (!pc.IsValidGeometry())
                return EnumEditorCode.Processed;

            var u = pc.ComputeClosestPoint(pickedItem.GetPosition().ToPnt());
            if (u == double.NaN)
                return EnumEditorCode.Processed;

            var pt = pc.Value(u);

            pt.Transform(se.GetTransform().Inverted());

            UndoTransaction undo = new UndoTransaction(doc);
            undo.Start(GetName());

            var pe = PointElement.Create(doc);
            pe.SetValue(pt);
            pe.SetParentId(se.GetId());
            pe.SetTransformBehaviour(EnumTransformBehaviour.ByParent);

            undo.Commit();

            return EnumEditorCode.Processed;
        }

        public override EnumEditorCode OnMouseUp(ViewContext ctx, InputEvent evt)
        {
            if(evt.GetButtons() == EnumMouseButton.Left)
            {
                var hilight = ctx.GetSelectionManager().GetHilight();
                if(hilight.GetCount() > 0)
                {
                    var pickedItem = hilight.GetItem(0);
                    return AddMethod2(ctx, evt, pickedItem);
                }
            }

            return base.OnMouseUp(ctx, evt);
        }
    }
}
